package Connectivity;
import java.util.ArrayList;
import Command.LDrawPart;
import Common.Matrix4;
import Common.Vector3f;
import LDraw.Files.LDrawMPDModel;
import LDraw.Files.LDrawModel;
import LDraw.Support.LDrawDirective;
import LDraw.Support.MatrixMath;
import LDraw.Support.type.LDrawGridTypeT;
import Window.MOCBuilder;
public abstract class Connectivity implements Cloneable, IConnectivity {
public static enum TYPE {
Axle, Ball, Hole, Stud, Fixed, Gear, Hinge, Rail, Slider, CollisionBox, BoundingAABB, Comment, Import
}
protected Matrix4 transformMatrix = Matrix4.getIdentityMatrix4();
protected Vector3f currentPos = new Vector3f();
protected Vector3f directionVector = null;
protected Direction6T direction = Direction6T.Y_Minus;
protected int type;
protected String fileName;
protected LDrawPart parent = null;
private boolean isSelected = false;
private ArrayList<Connectivity> connectedConnectivity;
public boolean isSelected() {
return this.isSelected;
}
public void setSelected(boolean flag) {
this.isSelected = flag;
}
public Matrix4 getTransformMatrix() {
return new Matrix4(transformMatrix);
}
public void setTransformMatrix(Matrix4 mat) {
this.transformMatrix = new Matrix4(mat);
}
public Vector3f getTranslationVector() {
return new Vector3f(transformMatrix.element[3][0],
transformMatrix.element[3][1], transformMatrix.element[3][2]);
}
public int gettype() {
return type;
}
public void settype(String type) {
try {
this.type = Integer.parseInt(type);
} catch (Exception e) {
System.out.println(getFileName());
}
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int parseString(String line[]) {
settype(line[1]);
for (int column = 0; column < 4; column++) {
for (int row = 0; row < 3; row++) {
transformMatrix.element[column][row] = Float.parseFloat(line[2
+ column * 3 + row]);
}
}
fileName = line[line.length - 1];
return 13;
}
public String toString(String details) {
String transform = String.format(
"%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f",
transformMatrix.element[0][0], transformMatrix.element[0][1],
transformMatrix.element[0][2], transformMatrix.element[1][0],
transformMatrix.element[1][1], transformMatrix.element[1][2],
transformMatrix.element[2][0], transformMatrix.element[2][1],
transformMatrix.element[2][2], transformMatrix.element[3][0],
transformMatrix.element[3][1], transformMatrix.element[3][2]);
if (details != null) {
return String.format("%d %d %s %s %s",
TYPE.valueOf(getClass().getName().substring(13)).ordinal(),
type, transform, details, fileName);
} else {
return String.format("%d %d %s %s",
TYPE.valueOf(getClass().getName().substring(13)).ordinal(),
type, transform, fileName);
}
}
public abstract String getName();
public Object clone() throws CloneNotSupportedException {
Connectivity a = (Connectivity) super.clone();
a.transformMatrix = new Matrix4(transformMatrix);
a.parent = parent;
a.currentPos = (Vector3f) currentPos.clone();
return a;
}
public void setParent(LDrawPart parent) {
this.parent = parent;
}
public LDrawPart getParent() {
return this.parent;
}
public static boolean isConnectable(Connectivity conn1, Connectivity conn2) {
if (conn1.gettype() % 2 == 1)
if (conn1.gettype() - 1 == conn2.gettype())
return true;
if (conn2.gettype() % 2 == 1)
if (conn2.gettype() - 1 == conn1.gettype())
return true;
return false;
}
public Direction6T getDirection() {
return direction;
}
@Override
public void updateConnectivityOrientationInfo() {
if (parent == null)
return;
// update curentPos
Vector3f newPos = getCurrentPos(parent.transformationMatrix());
currentPos.set(newPos);
// update direction
this.direction = getDirection(parent.transformationMatrix());
// update direction vector
this.directionVector = getDirectionVector(parent.transformationMatrix());//
}
@Override
public Direction6T getDirection(Matrix4 partTransformMatrix) {
return Direction6T.getDirectionOfTransformMatrix(Matrix4.multiply(
getTransformMatrix(), partTransformMatrix));
}
@Override
public Vector3f getDirectionVector() {
if (directionVector == null)
updateConnectivityOrientationInfo();
return directionVector;
}
@Override
public Vector3f getDirectionVector(Matrix4 newTransformMatrix) {
Vector3f directionVector = new Vector3f(0, 1, 0);
directionVector = MatrixMath.V3RotateByTransformMatrix(directionVector,
getTransformMatrix());
directionVector = MatrixMath.V3RotateByTransformMatrix(directionVector,
newTransformMatrix);
return directionVector;
}
@Override
public Vector3f getCurrentPos(Matrix4 partTransformMatrix) {
Vector3f newPos = new Vector3f(0, 0, 0);
newPos = getTransformMatrix().transformPoint(newPos);
newPos = partTransformMatrix.transformPoint(newPos);
return newPos;
}
@Override
public Vector3f getCurrentPos() {
return currentPos;
}
@Override
public ConnectivityTestResultT isConnectable(IConnectivity connector) {
if (this.getClass().isInstance(connector) == true) {
if (this.gettype() % 2 == 1)
if (this.gettype() - 1 == ((Connectivity) connector).gettype())
return ConnectivityTestResultT.True;
if (((Connectivity) connector).gettype() % 2 == 1)
if (((Connectivity) connector).gettype() - 1 == this.gettype())
return ConnectivityTestResultT.True;
}
return ConnectivityTestResultT.None;
}
@Override
public ConnectivityTestResultT isConnectable(
ArrayList<IConnectivity> connectors) {
if (connectors == null)
return ConnectivityTestResultT.None;
if (connectors.size() == 0)
return ConnectivityTestResultT.None;
if (connectors.size() == 1)
return isConnectable(connectors.get(0));
return ConnectivityTestResultT.None;
}
@Override
public ConnectivityTestResultT isConnectable(
ArrayList<IConnectivity> connectors, Matrix4 partTransformMatrix) {
return isConnectable(connectors);
}
@Override
public ConnectivityTestResultT isConnectable(IConnectivity connector,
Matrix4 partTransformMatrix) {
ConnectivityTestResultT result = isConnectable(connector);
if (result != ConnectivityTestResultT.True)
return result;
if (getTransformMatrixForSnapConnecting((Connectivity) connector,
partTransformMatrix) != null)
return result;
return ConnectivityTestResultT.False;
}
@Override
public float distance(Vector3f testingPos) {
Vector3f distance = testingPos.sub(getCurrentPos());
return distance.dot(distance);
}
public Matrix4 getTransformMatrixForSnapConnecting(
Connectivity existingConn, Matrix4 initialTransformOfPart) {
Matrix4 newTransform = getRotationMatrixForConnection(existingConn,
initialTransformOfPart);
if (newTransform != null) {
newTransform.translate(initialTransformOfPart.element[3][0],
initialTransformOfPart.element[3][1],
initialTransformOfPart.element[3][2]);
Vector3f realMatchingPosOfExistingConn = existingConn
.getCurrentPos();
Vector3f realPosOfTestingConn = getCurrentPos(newTransform);
float distance = (float) (realMatchingPosOfExistingConn
.sub(getCurrentPos(initialTransformOfPart)).length());
if (MatrixMath.compareFloat(distance,
LDrawGridTypeT.Coarse.getXZValue() * 2) > 0)
return null;
Vector3f newPos = realMatchingPosOfExistingConn
.sub(realPosOfTestingConn);
newTransform.translate(newPos.x, newPos.y, newPos.z);
}
return newTransform;
}
public Matrix4 getRotationMatrixForConnection(Connectivity existingConn,
Matrix4 initialTransformMatrixOfPart) {
Matrix4 newMatrix = new Matrix4(initialTransformMatrixOfPart);
newMatrix.element[3][0] = newMatrix.element[3][1] = newMatrix.element[3][2] = 0;
LDrawPart existingPart = existingConn.getParent();
Matrix4 existingConnTransformMatrix = Matrix4.multiply(
existingConn.getTransformMatrix(),
existingPart.transformationMatrix());
for (int i = 0; i < 3; i++)
existingConnTransformMatrix.element[3][i] = 0;
Matrix4 testingConnTransformMatrix = Matrix4.multiply(
getTransformMatrix(), initialTransformMatrixOfPart);
for (int i = 0; i < 3; i++)
testingConnTransformMatrix.element[3][i] = 0;
Matrix4 candidate = Matrix4.multiply(
Matrix4.inverse(getTransformMatrix()),
existingConnTransformMatrix);
Direction6T direction6tCandidate = Direction6T
.getDirectionOfTransformMatrix(candidate);
Direction6T direction6tInitial = Direction6T
.getDirectionOfTransformMatrix(initialTransformMatrixOfPart);
if (getDirection().getValue() == direction6tCandidate.getValue()
|| getDirection().getValue() == direction6tInitial.getValue())
if (direction6tCandidate.getValue() != direction6tInitial
.getValue())
return null;
for (int i = 0; i < 3; i++)
candidate.element[3][i] = 0;
Matrix4 initMatrix = new Matrix4(initialTransformMatrixOfPart);
for (int i = 0; i < 3; i++)
initMatrix.element[3][i] = 0;
// System.out.println(getCurrentPos(initMatrix));
// System.out.println(getCurrentPos(candidate));
// System.out.println("#####################");
ArrayList<Matrix4> candidateForRotation = new ArrayList<Matrix4>();
candidateForRotation.add(candidate);
for (int i = 0; i < 3; i++) {
candidate = new Matrix4(candidate);
candidate.rotate((float) Math.toRadians(90),
existingConn.getDirectionVector());
candidateForRotation.add(candidate);
}
float posDiff = -1;
float posDiff2 = -1;
for (Matrix4 matrix : candidateForRotation) {
posDiff2 = matrix.getDifferentValueForRotation(initMatrix);
if (posDiff < 0) {
posDiff = posDiff2;
newMatrix = matrix;
} else if (posDiff > posDiff2 + 0.1f) {
posDiff = posDiff2;
newMatrix = matrix;
}
}
return newMatrix;
}
@Override
public Matrix4 transformationMatrixOfPart() {
return parent.transformationMatrix();
}
@Override
public void moveTo(Vector3f moveByInWorld) {
transformMatrix.element[3][0] = moveByInWorld.x;
transformMatrix.element[3][1] = moveByInWorld.y;
transformMatrix.element[3][2] = moveByInWorld.z;
updateConnectivityOrientationInfo();
}
@Override
public void moveBy(Vector3f moveByInWorld) {
transformMatrix.translate(moveByInWorld.x, moveByInWorld.y,
moveByInWorld.z);
updateConnectivityOrientationInfo();
}
@Override
public void rotateBy(float angle, Vector3f rotationVector) {
if (MatrixMath.compareFloat(angle, 0) == 0)
return;
Vector3f originalPos = transformMatrix.getDefaultTransformPos();
transformMatrix.rotate(angle, rotationVector);
moveTo(originalPos);
}
public Connectivity getConnectivity() {
return this;
}
public ArrayList<Connectivity> getConnectedConnectivity() {
if (connectedConnectivity == null || connectedConnectivity.size() == 0)
return null;
return connectedConnectivity;
}
public void addConnectedConnectivity(Connectivity connectedConnectivity) {
if (this.connectedConnectivity == null)
this.connectedConnectivity = new ArrayList<Connectivity>();
this.connectedConnectivity.add(connectedConnectivity);
}
public void removeConnectedConnectivity(Connectivity connectedConnectivity) {
if (this.connectedConnectivity == null)
return;
this.connectedConnectivity.remove(connectedConnectivity);
}
public void clearConnectedConnectivity() {
if (this.connectedConnectivity == null)
return;
this.connectedConnectivity.clear();
}
}